package com.jayanslow.lighting.server.parser;

import com.jayanslow.lighting.protocol.commands.Dmx;
import com.jayanslow.lighting.protocol.commands.Dmx.DmxCommand;
import com.jayanslow.lighting.server.dmx.DmxController;
import com.jayanslow.lighting.server.dmx.OverflowException;

public class DmxParser {
	
	DmxController d;
	short[] data;
	public short[] startParse(DmxController d, short[] ss) {
		this.d = d;
		this.data = ss;
		DmxCommand cmd = DmxCommand.valueOf(ss[0]);
		try {
			switch (cmd) {
				case GET:
					return get();
				case GET_RANGE:
					return getRange();
				case GET_ALL:
					return getAll();
				case SET:
					return set();
				case SET_FADE:
					return setFade();
				case SET_RANGE:
					return setRange();
				case SET_RANGE_FADE:
					return setRangeFade();
				default:
					return Errors.COMMAND.getArray();
			}
		} catch (Exception e) {
			return Errors.UNKNOWN.getArray();
		}
	}

	private short[] get() {
		if (data.length != 3) return Errors.FORMAT.getArray();
		short chan = Dmx.toChannel(data[1], data[2]);
		short val;
		
		try { val = d.getChannel(chan).getValue(); }
		catch (OverflowException e) { return Errors.UNKNOWN.getArray(); }
		
		return new short[] { DmxCommand.GET.getCode(), val };
	}
	private short[] getRange() {
		if (data.length != 5) return Errors.FORMAT.getArray();
		short start = Dmx.toChannel(data[1], data[2]);
		short end = Dmx.toChannel(data[3], data[4]);
		if (start > end) {
			short temp = end;
			end = start;
			start = temp;
		}
		short[] r = new short[end - start + 2];
		r[0] = DmxCommand.GET_RANGE.getCode();
		
		for (short i = start; i <= end; i++) {
			try { r[i - start + 1] = d.getChannel(i).getValue(); }
			catch (OverflowException e) { return Errors.UNKNOWN.getArray(); }
		}
		
		return r;
	}

	private short[] getAll() {
		short start = Dmx.CHAN_MIN, end = Dmx.CHAN_MAX;
		short[] r = new short[end - start + 2];
		r[0] = DmxCommand.GET_ALL.getCode();
		
		for (short i = start; i <= end; i++) {
			try { r[i - start + 1] = d.getChannel(i).getValue(); }
			catch (OverflowException e) { return Errors.UNKNOWN.getArray(); }
		}
		
		return r;
	}
	private short[] set() {
		if (data.length != 4) return Errors.FORMAT.getArray();
		short chan = Dmx.toChannel(data[1], data[2]);
		short val = Dmx.toValue(data[3]);
		
		try {  d.getChannel(chan).setValue(val); }
		catch (OverflowException e) { return Errors.UNKNOWN.getArray(); }
		
		return new short[] { DmxCommand.SET.getCode() };
	}
	private short[] setFade() {
		if (data.length != 7) return Errors.FORMAT.getArray();
		short chan = Dmx.toChannel(data[1], data[2]);
		short val = Dmx.toValue(data[3]);
		int time = Dmx.toTime(data[4],data[5],data[6]);
		
		try {  d.getChannel(chan).addSimpleFade(time, val); }
		catch (OverflowException e) { return Errors.UNKNOWN.getArray(); }
		
		return new short[] { DmxCommand.SET_FADE.getCode() };
	}
	private short[] setRange() {
		if (data.length != 6) return Errors.FORMAT.getArray();
		short start = Dmx.toChannel(data[1], data[2]);
		short end = Dmx.toChannel(data[3], data[4]);
		short val = Dmx.toValue(data[5]);
		if (start > end) {
			short temp = end;
			end = start;
			start = temp;
		}
		
		for (short i = start; i <= end; i++) {
			try { d.getChannel(i).setValue(val); }
			catch (OverflowException e) { return Errors.UNKNOWN.getArray(); }
		}
		
		return new short[] { DmxCommand.SET_RANGE.getCode() };
	}
	private short[] setRangeFade() {
		if (data.length != 9) return Errors.FORMAT.getArray();
		short start = Dmx.toChannel(data[1], data[2]);
		short end = Dmx.toChannel(data[3], data[4]);
		short val = Dmx.toValue(data[5]);
		int time = Dmx.toTime(data[6],data[7],data[8]);
		if (start > end) {
			short temp = end;
			end = start;
			start = temp;
		}
		
		for (short i = start; i <= end; i++) {
			try { d.getChannel(i).addSimpleFade(time, val); }
			catch (OverflowException e) { return Errors.UNKNOWN.getArray(); }
		}
		
		return new short[] { DmxCommand.SET_RANGE_FADE.getCode() };
	}
}
